from typing import List


def vector_add(v1: List, v2: List) -> List:
    '''
    向量加法
    输入 向量一 向量二
    返回 向量加法结果
    '''
    return [ v1[i] + v2[i] for i in range(len(v1))]


def vector_mul(v1: List, v2: List) -> int:
    '''
    向量乘法
    输入 向量一 向量二
    返回 向量乘积结果
    '''
    return sum([ v1[i] * v2[i] for i in range(len(v1))])

def augmentation(v: List) -> List:
    '''
    感知器算法中特征矢量的增广化
    输入 特征矢量
    返回 增广特征矢量
    '''
    return [1] + v

def PLA_single(s1: List[List], s2: List[List], w: List, order=None) -> List:
    '''
    单样本调整的感知器算法
    输入 样本集合一 样本集合二 初始权值向量 样本更新序列
    输出 感知器准则函数权值向量
    '''
    # 如果没有给定样本更新序列，那就按照样本集合决定顺序 
    if order is None:
        order = s1 + s2

    # 将每个样本进行增广化
    order = [ augmentation(o) for o in order ]

    # 将s2中的样本都乘以-1 得到新的样本更新序列
    ord = []
    for s in order:
        if s[1:] in s2:
            ord.append([-ss for ss in s])
        else:
            ord.append(s)



    # 分析轮数
    idx = 0
    # 被正确识别的样本数
    cnt = 0
    while True:
        i = idx % len(ord)

        print("当前轮数为:",idx+1)
        print("当前权值向量为:",w)
        print("本轮识别的样本为:", order[i][1:])

        res = vector_mul(w,ord[i])
        print
        # 当前样本被正确识别 
        if res > 0:
            print("正确识别了样本")
            cnt += 1
            # 全部样本均被正确识别
            if cnt == len(ord):
                break
        # 当前样本被错误识别
        else:
            print("错误识别了样本,权向量更新")
            w = vector_add(w,ord[i])
            cnt = 0
        
        idx = idx + 1
        print()
    print("所有样本识别成功",end="\n\n")

    return w








# for debug
# v1 = [4,3,6]
# v2 = [2,-2,3]
# v3 = [1,0,-3] 
# v4 = [4,2,3]

# N = [v1,v4]
# P = [v2,v3]
# order = [v1, v2, v3 ,v4]



# w = PLA_single(N,P,[1,0,0,0],order=order)
# print(w)

